"""Locale utility routines."""

__all__ = ["localelist", "encoding", "getpair"]

import sys

try:
    import locale
except ImportError:
    locale = None

try:
    import codecs
except ImportError:
    codecs = None

def localelist(*locales):
    """Normalize and return a list of locales, with appended defaults.

    e.g. on a system with en_US as the default locale,

    localelist('en_GB.utf8', 'de_DE') =>
        ['en_GB', 'en', 'de_DE', 'de', 'en_US', 'C']

    """

    locales = list(locales)

    if locale is not None:
        # Set the locale if it hasn't already been set, but don't fail
        # if we can't set it for some reason.
        if locale.getlocale(locale.LC_COLLATE)[0] is None:
            try:
                locale.setlocale(locale.LC_COLLATE, '')
            except locale.Error:
                pass

        # Throw in the user's specified collation locale, the current locale,
        # the default locale, and POSIX, for free.
        locales.append(locale.getlocale(locale.LC_COLLATE)[0])
        locales.append(locale.getlocale()[0])
        locales.append(locale.getdefaultlocale()[0])
    locales.append("C")

    # Don't put the same locale in the return list more than twice.
    added = set()
    retlist = []

    for locale_ in locales:
        if not locale_:
            continue
        if locale is not None:
            locale_ = locale.normalize(locale_)
        # Strip off encoding if present.
        locale_ = locale_.split(".")[0]
        if locale_.lower() not in added:
            retlist.append(locale_)
            added.add(locale_.lower())
        # Strip off territory if present.
        locale_ = locale_.split("_")[0]
        if locale_.lower() not in added:
            retlist.append(locale_)
            added.add(locale_.lower())

    return retlist

def encoding(preferred=None):
    """Try to find an optimal encoding.

    Arguments:
    preferred - use this encoding if possible

    Otherwise, the locale encoding or the Python system encoding are
    used.
    """
    # can't use any codecs, use the system one (ascii).
    if codecs is None:
        return sys.getdefaultencoding()

    # if preferred is a valid codec, use it.
    if preferred is not None:
        try:
            return codecs.lookup(preferred).name
        except (LookupError, AttributeError):
            pass

    # preferred is bad and can't get it from locale.
    if locale is None:
        return sys.getdefaultencoding()

    # try to get it from the locale, if not there, set it and try again.
    fromlocale = locale.getlocale(locale.LC_COLLATE)[1]
    if fromlocale is not None:
        return fromlocale
    try:
        locale.setlocale(locale.LC_COLLATE, '')
    except locale.Error:
        pass
    else:
        fromlocale = locale.getlocale(locale.LC_COLLATE)
        if fromlocale is not None:
            return fromlocale

    # okay, LC_COLLATE isn't set, maybe the generic locale is.
    fromlocale = locale.getlocale()[1]
    if fromlocale is not None:
        return fromlocale

    # but we won't reset the generic locale if it isn't, that'd be
    # rude.

    # if the locale can't even give us a simple encoding, go back
    # to the system one, and give up.
    return locale.getpreferredencoding() or sys.getdefaultencoding()

def getpair(locale_, encoding_):
    """If encoding_ is unspecified, get the locale encoding."""
    if "." in locale_:
        if encoding_ is None:
            locale_, encoding_ = locale_.rsplit(".", 1)
        else:
            locale_ = locale_.rsplit(".")[0]
    return locale_, encoding(encoding_)
    
